package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.zzyl.constant.RedisConstant;
import com.zzyl.dto.ResourceDto;
import com.zzyl.entity.Resource;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.ResourceMapper;
import com.zzyl.service.ResourceService;
import com.zzyl.utils.NoProcessing;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.vo.ResourceVo;
import com.zzyl.vo.TreeItemVo;
import com.zzyl.vo.TreeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;

    /**
     * 获取分页查询资源列表
     * @param resourceDto
     * @return
     */
    //查询是加入缓存    增删改时删除缓存
    @Cacheable(cacheNames= RedisConstant.RESOURCE_LIST,key = "#resourceDto.hashCode()")
    @Override
    public List<ResourceVo> getResourceList(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        List<ResourceVo> resourceVoList = resourceMapper.getResourceList(resource);
        return resourceVoList;
    }

    /**
     * 获取资源树
     * @param resourceDto
     * @return
     */
    @Cacheable(value = RedisConstant.RESOURCE_TREE)
    @Override
    public TreeVo getresourceTreeVo(ResourceDto resourceDto) {
        //查询所有菜单数据
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        resource.setResourceType("m");
        resource.setDataState("0");
        List<ResourceVo> resourceList = resourceMapper.getResourceList(resource);
        //用于装所有数据
        List<TreeItemVo> treeItemVos = new ArrayList<>();
        //根目录
        ResourceVo root = new ResourceVo();
        root.setResourceNo("100001000000000");
        root.setResourceName("智慧养老院");
        //从一级一下开始递归
        recursionTree(treeItemVos, root, resourceList);
        TreeVo treeVo = new TreeVo();
        treeVo.setItems(treeItemVos);
        return treeVo;
    }

    /**
     * 递归构造树结构
     * @param treeItemVos
     * @param root
     * @param resourceList
     */
    private void recursionTree(List<TreeItemVo> treeItemVos, ResourceVo root, List<ResourceVo> resourceList) {
        //先创建根目录对象
        TreeItemVo itemVo = new TreeItemVo();
        itemVo.setId(root.getResourceNo());
        itemVo.setLabel(root.getResourceName());
        //构造根目录下的一级菜单

        List<ResourceVo> childlist = resourceList
                .stream().filter(item -> item.getParentResourceNo().equals(root.getResourceNo()))
                .collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(childlist)) {
            //递归使用子集对象
            List<TreeItemVo> children = new ArrayList<>();

            childlist.forEach(res -> {
                recursionTree(children, res, resourceList);
            });
            //设置子集属性
            itemVo.setChildren(children);
        }
        treeItemVos.add(itemVo);
    }

    //添加资源
    @Caching(evict = {@CacheEvict(value = RedisConstant.RESOURCE_TREE, allEntries = true),
            @CacheEvict(value = RedisConstant.RESOURCE_LIST, allEntries = true)})
    @Override
    public void addresource(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        //添加资源   先获取要添加资源菜单的父编号resourceparentno  查看他下面有几级菜单  求resourceNo  进行操作
        String parentResourceNo = resource.getParentResourceNo();
        String resourceNo = createResourceNo(parentResourceNo);
        resource.setResourceNo(resourceNo);
        resourceMapper.insert(resource);
    }

    //添加资源方法

    private String createResourceNo(String parentResourceNo) {
        //1.先判断父级菜单是否大于3级   大于三级不行  要小于三级
        //需要调用方法把多余的000去掉
        //如果大于三级 不行
        if (NoProcessing.processString(parentResourceNo).length() / 3 >= 5) {
            throw new BaseException(BasicEnum.RESOURCE_DEPTH_UPPER_LIMIT);
        }
        //如果小于三级 接受父级菜单下所有子集
        Resource resource = new Resource();
        resource.setParentResourceNo(parentResourceNo);
        List<ResourceVo> resourceList = resourceMapper.getResourceList(resource);
        //判断是否有子集   如果没有子集  直接拼接1 然后拼接  如
        if (ObjectUtil.isEmpty(resourceList)) {
            //工具类方法 在父级下创建一个新的子级      100 001 001 001 新增 001   二级菜单下新增三级菜单
            return NoProcessing.createNo(parentResourceNo, false);
        }
        //果有子集  获取子集的数量  +1
        String maxresourceNo = resourceMapper.selectcount(parentResourceNo);
        return NoProcessing.createNo(maxresourceNo, true);

    }

    //修改资源
    @Caching(evict = {@CacheEvict(value = RedisConstant.RESOURCE_TREE, allEntries = true),
            @CacheEvict(value = RedisConstant.RESOURCE_LIST, allEntries = true)})
    @Override
    public void updateResource(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        resourceMapper.updateResource(resource);
    }

    //启用禁用
    @Caching(evict = {@CacheEvict(value = RedisConstant.RESOURCE_TREE, allEntries = true),
            @CacheEvict(value = RedisConstant.RESOURCE_LIST, allEntries = true)})
    @Override
    public void isEnable(ResourceDto resourceDto) {
        Resource resource = BeanUtil.toBean(resourceDto, Resource.class);
        String parentResourceNo = resource.getParentResourceNo();
        // 查询父类的状态
        String parentDataState = resourceMapper.getDataStateByResourceNo(parentResourceNo);
        // 如果父类状态为1，且子类想要启用，则抛出异常或返回错误
        if (parentDataState.equals("1") && resource.getDataState().equals("0")) {
            throw new BaseException(BasicEnum.PARENT_MENU_DISABLE);
        }
        //更新父级状态
        resourceMapper.isEnable(resource);
        //更新子级状态
        //获取父类部门编号 把后面的0去掉
        String resourceNo = NoProcessing.processString(resource.getResourceNo());
        if (resource.getDataState().equals("0")) {
            resourceMapper.isEnableson(resourceNo, "0");
        } else if (resource.getDataState().equals("1")) {
            resourceMapper.isEnableson(resourceNo, "1");
        }
    }

    //删除资源
    @Caching(evict = {@CacheEvict(value = RedisConstant.RESOURCE_TREE, allEntries = true),
            @CacheEvict(value = RedisConstant.RESOURCE_LIST, allEntries = true)})
    @Override
    public void deleteResource(String resourceNo) {
        Resource resource = new Resource();
        resource.setParentResourceNo(resourceNo);
        //查看该资源下是否有子集
        if (ObjectUtil.isNotEmpty(resourceMapper.getResourceList(resource))) {
            throw new RuntimeException("存在下级菜单,不允许删除");
        }
        resourceMapper.deleteResource(resourceNo);

    }

}
